package sql;

import java.util.ArrayList;
import java.util.List;

/**
 * 一个用于将包含多条SQL语句的字符串分割成单独语句列表的工具类。
 * 它会尝试处理字符串常量、单行注释和多行注释中的分号。
 */
public class SQLStatementSplitter {

    // 定义状态常量
    private static final int STATE_NORMAL = 0;
    private static final int STATE_IN_SINGLE_QUOTE = 1;
    private static final int STATE_IN_DOUBLE_QUOTE = 2; // Handles double quoted strings/identifiers
    private static final int STATE_IN_DASH_COMMENT = 3;
    private static final int STATE_IN_BLOCK_COMMENT = 4;

    /**
     * 将包含一个或多个SQL语句的字符串分割成单独的语句列表。
     * 语句通常以分号(;)分隔，但会忽略在引号内或注释内的分号。
     * 
     * @param batchSql 包含一个或多个SQL语句的字符串。
     * @return 一个包含单独SQL语句字符串的列表。如果输入为空或null，则返回空列表。
     */
    /**
     * 分割包含多个SQL语句的字符串，正确处理字符串常量和注释中的分号
     *
     * @param batchSql 包含多个SQL语句的字符串，以分号分隔
     * @return 分割后的SQL语句列表，已去除空语句
     */
    public static List<String> split(String batchSql) {
        List<String> statements = new ArrayList<>();
        if (batchSql == null || batchSql.trim().isEmpty()) {
            return statements;
        }

        // 规范化输入：去除BOM字符和首尾空白
        batchSql = batchSql.trim();
        if (batchSql.startsWith("\uFEFF")) { // 处理UTF-8 BOM
            batchSql = batchSql.substring(1);
        }

        System.out.println("[DEBUG SQLStatementSplitter] 开始分割SQL批处理: " + batchSql);

        StringBuilder currentStatement = new StringBuilder();
        int state = STATE_NORMAL;
        char[] chars = batchSql.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];

            switch (state) {
                case STATE_NORMAL:
                    if (c == '\'') { // Correct character literal
                        state = STATE_IN_SINGLE_QUOTE;
                        currentStatement.append(c);
                    } else if (c == '"') { // Correct character literal
                        state = STATE_IN_DOUBLE_QUOTE;
                        currentStatement.append(c);
                    } else if (c == '-' && i + 1 < chars.length && chars[i + 1] == '-') {
                        state = STATE_IN_DASH_COMMENT;
                        i++; // Skip the next '-'
                    } else if (c == '/' && i + 1 < chars.length && chars[i + 1] == '*') {
                        state = STATE_IN_BLOCK_COMMENT;
                        i++; // Skip the '*'
                    } else if (c == ';') {
                        String stmt = currentStatement.toString().trim();
                        if (!stmt.isEmpty()) {
                            statements.add(stmt);
                            System.out.println("[DEBUG SQLStatementSplitter] 添加语句: " + stmt);
                        }
                        currentStatement.setLength(0);
                    } else {
                        currentStatement.append(c);
                    }
                    break;

                case STATE_IN_SINGLE_QUOTE:
                    currentStatement.append(c);
                    if (c == '\'') { // Correct character literal // Current char c is a quote
                        // Check if this is an escaped quote ''
                        if (i + 1 < chars.length && chars[i + 1] == '\'') { // Correct character literal
                            // It's an escaped quote ''. We've already appended the first ' (c).
                            // We need to skip the next ' so it's treated as part of the escape.
                            i++; // Advance i to skip the second ' of the pair.
                                 // The state remains STATE_IN_SINGLE_QUOTE.
                        } else {
                            // It's a non-escaped quote, so it's the end of the string.
                            state = STATE_NORMAL;
                        }
                    }
                    break;

                case STATE_IN_DOUBLE_QUOTE:
                    currentStatement.append(c);
                    if (c == '"') { // Correct character literal // Current char c is a double quote
                        // Check if this is an escaped quote ""
                         if (i + 1 < chars.length && chars[i + 1] == '"') { // Correct character literal
                            // It's an escaped quote "". We've already appended the first " (c).
                            // We need to skip the next " so it's treated as part of the escape.
                            i++; // Advance i to skip the second " of the pair.
                                 // The state remains STATE_IN_DOUBLE_QUOTE.
                         } else {
                            // It's a non-escaped quote, so it's the end of the string/identifier.
                             state = STATE_NORMAL;
                         }
                    }
                    break;

                case STATE_IN_DASH_COMMENT:
                    if (c == '\n') {
                        state = STATE_NORMAL;
                        // Append newline to maintain relative line structure if needed,
                        // but splitter usually discards comments and their formatting.
                        // Let's append it to currentStatement for potential debugging/structure.
                        currentStatement.append(c);
                    }
                    // Ignore other comment characters
                    break;

                case STATE_IN_BLOCK_COMMENT:
                    if (c == '*' && i + 1 < chars.length && chars[i + 1] == '/') {
                        state = STATE_NORMAL;
                        i++; // Skip the '/'
                    }
                    // Ignore comment characters
                    break;
            }
        }

        // 处理最后一条语句（可能没有以分号结尾）
        String lastStmt = currentStatement.toString().trim();
        if (!lastStmt.isEmpty()) {
            // 检查是否在注释或字符串中结束
            if (state == STATE_NORMAL) {
                statements.add(lastStmt);
                System.out.println("[DEBUG SQLStatementSplitter] 添加最后一条语句: " + lastStmt);
            } else {
                System.out.println("[WARN] SQLStatementSplitter: 检测到未闭合的" +
                    (state == STATE_IN_SINGLE_QUOTE ? "单引号字符串" :
                     state == STATE_IN_DOUBLE_QUOTE ? "双引号字符串" :
                     state == STATE_IN_DASH_COMMENT ? "单行注释" : "多行注释") +
                    "，最后一条语句可能不完整");
            }
        }

        System.out.println("[DEBUG SQLStatementSplitter] 分割完成，共 " + statements.size() + " 条语句");
        return statements;
    }

}